容器是一種輕量化的打包技術, 它將硬體層拆開, 只保留軟體層的部分, 其中運行的項目為映像檔。Docker 是創建容器的工具, 我們透過他創建的容器來運行映像檔, 工程師完成容器後就可以在實體機、虛擬機或雲端上運行, 經過容器打包之後的映像檔可以在不同的作業系統中運行。
使用映像檔來發布應用程式可以確保從工程師手上到正式環境的應用程式都是一致的。
映像檔是一個靜態檔案, 具有不可變性, 有異動時就要重新打包,
它必須在容器中才能運作, 同一份映像檔可以在多個不同的容器中運行。
每個容器有自己的IP, 各容器間相互隔離, 資源不共享。
映像檔(Image)
是一個靜態模板, 裡面包了一個完整的服務, 需要在容器中才能運行,
映像檔只檢查tag, 它透過 tag 管理每個映像檔的版本。部署時建議不要使用latest, 要加上tag版號, 因為latest是變動的, 不好掌握具體的版本號。在容器中執行時, 如果映像檔存在會直接使用本地映像檔, 不存在則會從遠端拉下來。
容器(Container)
倉庫(Registry)
Docker Hub 是公認官方最大的映像檔儲存倉庫,
存放在上面的映像檔只要透過容器啟動就可以在任何環境中運行。
採用主從式架構如下圖
圖片來源
Docker registry 和 Docker repository 的差別
在查Docker的時候一直有看到這兩個字眼, 所以google了一下發現有些不一樣 參考網址
Docker registry:
用於儲存 Docker images 的服務, 他可能是Public也可能是Private的image 可以透過第三方託管。
Docker repository
具有相同名稱但是不同tag的docker images 集合, 透過tag作為識別。
Dockerfile 是生成映像檔的配置文件, 每一行指令都是在描述映像檔中的每一層應該完成的行為。透過 Dockerfile 可以把所有環境建置流程寫進去,編寫完成後可以請人協助 code review, 降低可變性, 讓 build 出來的東西可以在不同環境中維持一致。
常用指令說明 詳細指令參考
1. FROM ... AS ... :
- 從哪一個image繼承
- ex: FROM golang:1.14.8 AS builder
2. ENTRYPOINT:
- 在container 啟動的時候要先跑什麼指令
3. RUN:
- 在這個container image 中跑什麼指令, 可以多個, 一行就是一句
- docker 預設在 / 根目錄底下 , 每一個RUN執行的指令互不影響
- ex:
FROM
RUN cd /tmp
RUN cd /var/log
RUN RUN echo ""World!"" > /hello.txt
最後停在 / 根目錄 因為 docker 預設就是在根目錄 , 如果要改變最後停止目錄要用 WORKDIR
4. COPY:
- 將本地端指定路徑的檔案把包到image裡面
- ex: COPY --from=builder /go/src/hello/hello /go/src/hello/env.example ./
5. ADD:
- 等同 COPY, 可以自動解壓縮會下載url, 若無解壓縮與下載需求建議使用 COPY
- ex: ADD ./ /go/src/hello
6. EXPOSE:
- 容易暴露出來的 port
- ex: EXPOSE 1031
7. WORKDIR:
- 切換執行目錄, 最後 WORKDIR 位置會成為容器啟動的執行目錄
- ex: WORKDIR /go/src/hello
8. LABEL:
- 設定映像檔的Metadata資訊
9. ENV:
- 設定環境變數
- ex: ENV GO111MODULE=on
10. 文件可以使用 `#` 來進行註解
build 指令
docker build -t name -f Dockerfile .
最後要加上 .
, 意思是把目前路徑所有檔案傳給 docker daemon
事先已在自己的github上推了一個具備http回應的專案
編寫 dockerfile
FROM golang:1.14.8
RUN git clone https://github.com/[---放http服務的地方].git /go/src/hello
RUN cd /go/src/hello && go build
WORKDIR /go/src/hello
EXPOSE 1031
ENTRYPOINT ["./hello"]
執行 Dockerfile ,最後記得加上 .
docker build -t hello -f Dockerfile .
執行結果
把image拉下來之後啟動
docker run --name hello -d -p 127.0.0.1:1031:1031 hello
檢查狀態, hello 正在執行中
測試打 docker 中的服務, 應該要取得當下時間
登入/登出 dockerhub
• docker login
• dokcer logout
image 操作 詳細參照
• docker images 或 docker image ls - 列出所有 image
• docker build - 打包 image
• docker history - 列出 image 各層資訊
• docker pull - 從遠端 docker registry 拉 image 下來
• docker push : 推送 image 到遠方 docker registry
• docker rmi 或 docker image rm - 刪掉 image
• docker save : 將 image 存到本地端
• docker tag - 為 image 更改 tag 作版本管理
docker pause
/docker unpause
: container 記憶體狀態會保存docker start
/docker stop
/docker restart
: container 記憶體狀態不會保存
Container 操作 詳細參照
• docker cp - 複製檔案 to/from container
• docker create - 建立 container, 但不啟動
• docker exec - 讓 container 執行指令
• docker kill - 強制終止 container
• docker logs - 呈現 container 的 log
• docker pause - 暫停 container
• docker ps - 列出運作中 container (加 -a 列出所有container, 包含暫停的)
• docker rm - 刪除容器
• docker run - create + start 建立後接著啟動
• docker restart - 重新啟動 container
• docker start - 啟動 container
• docker stats - container 資源使用狀態
• docker stop - 停止 container
• docker unpause - 繼續 container
Docker 本身具備很完整的功能, 從容器打包到部署一應俱全, 但是 Docker 適用於管理單一容器, 一旦開始使用越來越多的容器時, 為了要串起各個容器之間的網路, 跨容器的管理跟調度就會變得越來越困難,這些需求的累積一步步推動K8s的誕生,我想可以這麼說: K8s 是搭著容器的熱潮應運而生的產物。